//3分钟搭建three场景

//开始
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { TWEEN } from 'three/examples/jsm/libs/tween.module.min';
import $ from 'jquery';
import { loaderModel,fbxLoaderModel,loaderGlbModel} from "./threeLoadModel"
import { CSS3DRenderer } from 'three/examples/jsm/renderers/css3drenderer';
import { computed } from 'vue';
import { dataListStore } from '../../stores/dataList'
import { ElMessage } from 'element-plus'
import gsap from "gsap";
let element = undefined;
let width = undefined;
let height = undefined;
let scene = undefined;
let camera = undefined;
let renderer = undefined;
let controls = undefined;
let mouse = {};
let mouseClick = {};
let mouseClickTime = undefined;
let raycaster = undefined;
let curObj = undefined;
//灯光
let ambientLight = undefined;
let directLight = undefined;
let textureCube = undefined;
let label3DRender =undefined;
let css3dLable = undefined;
let css3dLabelGroup = undefined;
let labelGroup = undefined;
let css3dLabelXQGroup = undefined;
let modelLcGroup = undefined;
let gridGroup = undefined;
const store = dataListStore();
let data = store.dataList;
let className = store.classNames;
const stateName = store.stateName; 
let modelAGroup = undefined;
let modelBGroup = undefined;
let modelCGroup = undefined;
let modelDGroup = undefined;

export function initThree(id) {
    //创建从vue页面加载three的入口
    THREE.Cache.enabled = true;
    element = document.getElementById(id);
    width = element.clientWidth;
    height = element.clientHeight;
    createGroup();
    //创建场景
    createScene();
    //创建摄像机
    createCamera();
    // createDaySky();
   // createbox();
    //创建灯光,白色环境光，光照强度为1
    createLight();
    //创建渲染器
    createRenderer();
    createControls();
    skyCube();
    css3DRenderer(width, height, element);
    pointGeometry();
    //create3dLable();
    //fbxLoaderModel(data, scene, css3dLabelGroup, labelGroup,css3dLabelXQGroup,modelLcGroup,modelAGroup,modelBGroup,modelCGroup,modelDGroup);
    window.showLabel = showLabel;
    window.closeLabel = closeLabel;

    window.alertInfo = alertInfo;
    //createGrid();
    loaderModel(data, scene, css3dLabelGroup, labelGroup, css3dLabelXQGroup, modelLcGroup,modelAGroup,modelBGroup,modelCGroup,modelDGroup);
    //loaderGlbModel(data, scene, css3dLabelGroup, labelGroup, css3dLabelXQGroup, modelLcGroup);
    //loaderObjModel(data, scene, css3dLabelGroup, labelGroup, css3dLabelXQGroup, modelLcGroup);
    
}

export function createGrid() {
  let num = 150;
  let radius = .9;
  let space = 750;
  let lineMat = new THREE.MeshBasicMaterial(0xffffff);
//   lineMat.transparent = true;
//   lineMat.opacity = 1;
  for (let i = 0; i < num; i++) {
    createLine(num, radius, space, i, lineMat);
  }
    createLine(num, radius, space, num, lineMat);
}

function createLine(num, radius, space, counter, linematerial) {
  let cloumnLine = new THREE.Mesh(new THREE.PlaneGeometry(num * space, radius), linematerial);
  cloumnLine.rotateX(-Math.PI * .5);
  cloumnLine.position.z += (counter * space) - (num * space / 2);
  cloumnLine.position.y = 10;
  let rowLine = cloumnLine.clone();
  rowLine.position.set(0, 10, 0);
  rowLine.rotateZ(-Math.PI * .5);
  rowLine.position.x += (counter * space) - (num * space / 2);
  rowLine.position.y = 10;
  gridGroup.add(cloumnLine, rowLine);
}
function createGroup() {
    css3dLabelGroup = new THREE.Group();
    css3dLabelGroup.name = "css3dLabelGroup";
    labelGroup = new THREE.Group();
    labelGroup.name = "labelGroup";
    css3dLabelXQGroup = new THREE.Group();
    css3dLabelXQGroup.name = "css3dLabelXQGroup";
    modelLcGroup = new THREE.Group();
    modelLcGroup.name = "modelLcGroup";
    gridGroup= new THREE.Group();
    gridGroup.name = "gridGroup";
    modelAGroup= new THREE.Group();
    modelAGroup.name = "modelAGroup";
    modelBGroup= new THREE.Group();
    modelBGroup.name = "modelBGroup";
    modelCGroup= new THREE.Group();
    modelCGroup.name = "modelCGroup";
    modelDGroup= new THREE.Group();
    modelDGroup.name = "modelDGroup";
    
    
}

function createScene() {
    scene = new THREE.Scene();
    //scene.background = new THREE.Color(0,0,0);
    scene.add(css3dLabelGroup);
    scene.add(labelGroup);
    scene.add(css3dLabelXQGroup);
    scene.add(modelLcGroup);
    scene.add(gridGroup);
    scene.add(modelAGroup);
    scene.add(modelBGroup);
    scene.add(modelCGroup);
    scene.add(modelDGroup);
}
function createCamera() {
    camera = new THREE.PerspectiveCamera(45,width/height,1,80000000);
    camera.position.z = 100;
}

function createLight() {
    ambientLight = new THREE.AmbientLight(0xffffff,1);
    scene.add(ambientLight);
	// const spotLight = new THREE.SpotLight( 0xffffff,5,1000,Math.PI/10,0,2 );
	// spotLight.position.set( 100, 1000, 100 );
	// spotLight.castShadow = true;
	
	// spotLight.shadow.mapSize.width = 500;
	// spotLight.shadow.mapSize.height = 500;
	// spotLight.shadow.camera.near = 300;
	// spotLight.shadow.camera.far = 400;
	
	// scene.add( spotLight );
	
	// const spotLightHelper = new THREE.SpotLightHelper( spotLight );
	// scene.add( spotLightHelper );
 //    const light = new THREE.HemisphereLight( 0xffffff, 0x000000, 1 );
	// light.position.set(0,1000,0)
 //    scene.add(light);
    directLight = new THREE.DirectionalLight( 0xffffff, 1 );
    scene.add(directLight);
}
function createRenderer() {
    renderer = new THREE.WebGLRenderer({
        precision:'highp',
         alpha:true,
         antialias:true
    });
    renderer.shadowMap.enabled  = true;
     renderer.autoClear = true;
    renderer.outputEncoding = THREE.sRGBEncoding;//調整色彩飽和度
    // renderer.physicallyCorrectLights = false;
    // renderer.toneMappingExposure = 0.1;
    renderer.setPixelRatio(window.devicePixelRatio)
    renderer.setSize(width, height);
    //renderer.setClearColor( 0x263238 );
    //renderer.setPixelRatio(window.devicePixelRatio)
    // renderer.localClippingEnabled = true;
    element.appendChild(renderer.domElement);
    element.addEventListener('pointermove', mouseMove, false);
    element.addEventListener('pointerup', mouseUp, false);
    element.addEventListener('pointerdown', mouseDown, false);
}
function mouseMove() {
    mouse.x = ((window.event.clientX - element.getBoundingClientRect().left) / element.offsetWidth) * 2 - 1;
    mouse.y = -((window.event.clientY - element.getBoundingClientRect().top) / element.offsetHeight) * 2 + 1;
    document.body.style.cursor = 'default';
    raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouse, camera);
}
function mouseUp() {
    if (window.event.button == 0) {
        if (window.event.clientX - mouseClick.x <= 10 && window.event.clientY - mouseClick.y <= 10 && Date.now() - mouseClickTime < 150) {
            raycaster = new THREE.Raycaster();
            raycaster.setFromCamera(mouse, camera);
            //   let intersects = raycaster.intersectObject(scene);
            // console.log(intersects);
        }
    }else if (window.event.button == 2) {
        if (window.event.clientX - mouseClick.x <= 5 && window.event.clientY - mouseClick.y <= 5 && Date.now() - mouseClickTime < 150) {
            raycaster = new THREE.Raycaster();
            raycaster.setFromCamera(mouse, camera);
            initControl();
        }
    }
}
function mouseDown() {
    mouseClick.x = window.event.clientX;
    mouseClick.y = window.event.clientY;
    mouseClickTime = Date.now();
}
function createControls() {
    controls = new OrbitControls(camera, renderer.domElement);
    controls.object.position.set(-1076.6846871989233, 408.5020070483296, -602.633376408352);
    controls.target.set(-60.110525464626186, 111.94751770804038, 38.011516878125136);

}
//天空盒子
function skyCube() {
    var r = "static/model/skybox/";
    var urls = [ r + "nx.jpg", r + "ny.jpg",
        r + "nz.jpg", r + "px.jpg",
        r + "py.jpg", r + "pz.jpg" ];

    textureCube = new THREE.CubeTextureLoader().load( urls );
    textureCube.format = THREE.RGBFormat;
    textureCube.mapping = THREE.CubeReflectionMapping;
    //scene.background = textureCube;
}
function css3DRenderer(width, height, element) {
    label3DRender = new CSS3DRenderer();
    label3DRender.setSize(width, height);
    label3DRender.domElement.style.position = 'absolute';
    label3DRender.domElement.style.top = '0px';
    label3DRender.domElement.style.pointerEvents = 'none';
    element.appendChild(label3DRender.domElement);
}

function createbox() {
    let mesh = new THREE.Mesh(new THREE.BoxGeometry(30,10,10),new THREE.MeshBasicMaterial({
        color:0xffffff
    }));
    const axesHelper = new THREE.AxesHelper( 100 );
    scene.add( axesHelper );
    //scene.add(mesh)
    let start = new THREE.Vector3( 11.845133379741005,2.5,-50 );
    let end = new THREE.Vector3(-11.845133379741005, 2.5, -3);

    let target = new THREE.Vector3();
    let line = new THREE.Line3(start, end);
    line.at(0.5, target);
    mesh.position.copy(target)
    const points = [];
    points.push( start );
    points.push(end);
    const material = new THREE.LineBasicMaterial({
	    color: 0xff00ff
    });
    const geometry = new THREE.BufferGeometry().setFromPoints( points );
    const lines = new THREE.Line( geometry, material );
    scene.add( lines );
    let angles = angle(start, end);
    
}
function angle(a,b) {
     var dx = b.x - a.x;
    var dy = b.z - a.z;
    var dis = Math.sqrt(dx * dx + dy * dy);
    var rota = dis > 0 ? Math.round(Math.asin(dy / dis) / Math.PI * 180) : 0;
    // rota范围（-90，90）当b点在a点左边时，必要另处理
    if (b.x < a.x) {
        rota = 180 - rota;
    }
    return rota;

}
function getDeg() {
    if (css3dLabelGroup && css3dLabelGroup.children.length > 0) {
        const bodyDirection = camera.getWorldDirection(new THREE.Vector3());
        css3dLabelGroup.children.map((item,index) => {
            item.rotation.y = -Math.atan2(bodyDirection.x, bodyDirection.z) + Math.PI * 2;
            css3dLabelXQGroup.children[index].rotation.y = -Math.atan2(bodyDirection.x, bodyDirection.z) + Math.PI * 2;
        })
        
    }
}

function pointGeometry() {
    let geometry = new THREE.BoxGeometry(5, 5, 5);
    var starsMaterial = new THREE.PointsMaterial({
       color:0xfffff
    });
    for (var i = 0; i < 10000; i++) {
        var randomX = -13000+Math.round(Math.random()*30000);
        var randomY = -13000+Math.round(Math.random()*30000);
        var randomZ = -13000+Math.round(Math.random()*30000);
        let mesh = new THREE.Mesh(geometry, starsMaterial);
        mesh.position.x = randomX;
        mesh.position.y = randomY;
        mesh.position.z = randomZ;
        scene.add(mesh);
    }
   
   
    //projects.push(mesh)
}

export function showLabel(item,label) {
    seeMeshLabel( label );
    // console.log(item);
    // css3dLabelXQGroup.children.map(i => { 
    //     if (label == i.name && i.visible == false) { 
    //         i.visible = true;
    //     }
    // })
}
export function updateLabelColor() {
    let data = store.dataList;
    // css3dLabelGroup.children.map(i => {
    //     if (data.name == i.name) {
    //         $(`.${i.name}`).removeClass('normal').removeClass('yellow').removeClass('red').removeClass('fault').addClass(className[data.state])
    //     }
    // })
    let wz = "除尘器A侧右室";
    
    for( let key in data ){
        let item = data[key];
        if (item.hopper.indexOf('A1-') != -1 || item.hopper.indexOf('A2-') != -1) {
            wz = '除尘器A侧右室'
        } else if (item.hopper.indexOf('A3-') != -1 || item.hopper.indexOf('A4-') != -1) {
            wz = '除尘器A侧左室'
        }else if (item.hopper.indexOf('B1-') != -1 || item.hopper.indexOf('B2-') != -1) {
            wz = '除尘器B侧右室'
        }else if (item.hopper.indexOf('B3-') != -1 || item.hopper.indexOf('B4-') != -1) {
            wz = '除尘器B侧左室'
        }
        $(`.${key},.labelXq .${key} .center .labelNrHw,.labelXq .${key} .center .labelNrZt,.labelXq .${key} .center .labelNrHz,.labelXq .${key} .center .labelNrHzai,.labelXq .${key} .center .labelNrZhl,.labelXq .${key}.bottom`).removeClass('normal').removeClass('yellow').removeClass('red').removeClass('fault').removeClass('green').addClass(className[item.state])
        $(`.${key} .title span`).html(wz);
        $(`.labelXq .${key} .center .labelNrMc`).html(key);
        $(`.labelXq .${key} .center .labelNrHw`).html(item.height.toFixed(2) + '米');
        $(`.labelXq .${key} .center .labelNrZt`).html(stateName[item.state]);

        // $(`.labelXq .${key} .center .labelNrHz`).html(item.load.toFixed(2) + 't');
        //  $(`.labelXq .${key} .center .labelNrHzai`).html(item.load_rate.toFixed(2) + '%');
        // $(`.labelXq .${key} .center .labelNrZhl`).html(item.max_load.toFixed(2) + 't');
        $(`.labelXq .${key} .flex-press-more .in-press`).css({width: `${(item.load_rate.toFixed(4)*100) > 100 ? 100:item.load_rate.toFixed(4)*100}%`});
        $(`.labelXq .${key} .flex-press-more span`).removeClass('normal').removeClass('yellow').removeClass('red').removeClass('fault').removeClass('green').addClass(className[item.state]).text((item.load_rate.toFixed(4)*100).toFixed(2)+'%');
        $(`.labelXq .${key} .bc`).removeClass('flag');
        if( item.state == 0 && item.flag ){
            $(`.labelXq .${key} .bc`).addClass('flag');
        }
        let lable = css3dLabelXQGroup.getObjectByName(key);
        if (lable) {
            lable.visible = false;
            if( lable.userData.visible ){
                lable.visible = true;
            }else{
                let info = JSON.parse( localStorage.getItem( key ) );
                if (item.state == 1 || item.state == 2 || item.state == 3 || item.state == 4|| item.state == 5) {
                    if( info ){
                        if( info.state != item.state ){
                            lable.visible = true;
                            localStorage.removeItem( key );
                        }else if(  info.state == item.state  ){
                            if( item.time - info.time < 60 * 60 ){
                                lable.visible = false;
                            }else{
                                lable.visible = true;
                            }
                        }
                    }else{
                        lable.visible = true;
                    }
                }else{
                    if( item.flag ){
                        if( info ){
                            if( info.state != item.state ){
                                lable.visible = true;
                                localStorage.removeItem( key );
                            }else if(  info.state == item.state  ){
                                if( item.time - info.time < 60 * 60 ){
                                    lable.visible = false;
                                }else{
                                    lable.visible = true;
                                }
                            }
                        }else{
                            lable.visible = true;
                        }
                    }
                }
            }
            
        }
        getBl(key, item.height,item.state);
    }
}
function getBl( name, height ,state){
    height = height ? height : 0;
    if( name ){
        let needHd = store.modellcNameList[name];
        if (needHd) {
            let hdName = needHd.modelName;
            // console.log(modelLcGroup,hdName);
            let mesh = modelLcGroup.getObjectByName(hdName);
            if( mesh ){
				// let m = modelLcGroup.getObjectByName(hdName+'-top');
                let h = Number( mesh.userData.size.height );
                
                let chH = h / 6.4 * height;
                if( chH >= h ){
					chH = h; 
				}
                // mesh.material.clippingPlanes[0].constant = mesh.material.userData.initH + chH;
				// m.visible = false;
				
                let w = Number( mesh.userData.size.width );
                let d = Number( mesh.userData.size.depth );
                let s = chH / h;
                let sx = ( ( w - 4.65 ) * s + 4.65 ) / w;
                let sz = ( ( d - 4.65 ) * s + 4.65 ) / d;
                
                mesh.scale.set( sx * mesh.userData.scale.x, s * mesh.userData.scale.y, sz * mesh.userData.scale.z );
                mesh.position.y = mesh.userData.position.y - h * (1 - s) * 0.15; 
                upadteMateRial(mesh, state);
                

               //upadteMateRial(mesh, state);
            }
        }
    }
}

let textureNormal = new THREE.TextureLoader().load('static/colorNormal.jpg');
let textureYellow = new THREE.TextureLoader().load('static/colorYellow.jpg');
let textureGreen = new THREE.TextureLoader().load('static/colorGreen.jpg');
let textureRed = new THREE.TextureLoader().load('static/colorRed.jpg');
let textureFault = new THREE.TextureLoader().load('static/colorFault.jpg');

function upadteMateRial(mesh, data) {
    let map = textureNormal.clone();
    let emissive = 0x00ffff;
    if (data == 0) {
       emissive = 0x00ffff; 
       map = textureNormal.clone();
    } else if (data == 1) {
        emissive = 0xFFFF00; 
        map = textureGreen.clone(); 
    } else if (data == 2) {
        emissive = 0xFF6633;
        map = textureYellow.clone();
    } else if (data == 3 || data == 4) {
        emissive = 0xFF0000;
        map = textureRed.clone();
    } else if (data == 5) {
        emissive = 0xC0C0C0;
        map = textureFault.clone();
    }
   // console.log(mesh);
    mesh.material = mesh.material.clone(true);
    mesh.material.color = new THREE.Color(emissive);
    mesh.material.emissive = new THREE.Color(emissive);
    mesh.material.emissiveIntensity = 0.5;
    mesh.material.flatShading = true;
    mesh.material.metalness = 1.0;
    mesh.material.roughness = 0.0;

}

export function closeLabel(data, label) {
    let curObj = css3dLabelXQGroup.getObjectByName(label);
    if( curObj ){
        curObj.visible = false;
        curObj.userData.visible = false;
    }
    // css3dLabelXQGroup.children.map(item => {
    //     if (label == item.name) {
    //         item.visible = false;
    //         item.userData.visible = false;
    //     }
    // })
    localStorage.setItem( label, JSON.stringify({
        state: data.state,
        time: data.time
    } ))
    initControl();
}
export function alertInfo( a, b) {
    ElMessage({
        message: `实时灰重:${a.toFixed(2)}t/设计极限载灰量:${b.toFixed(2)}t`,
        type: 'warning',
      })
      return;
}
export function render() {
    getDeg();
    TWEEN.update();
    controls.update();

    directLight.position.x = camera.position.x + 1000;
    directLight.position.y = camera.position.y + 1000;
    directLight.position.z = camera.position.z + 1000;

    //console.log(controls.object.position,controls.target);
    if ( label3DRender ) {
        label3DRender.render(scene, camera);
    }
    renderer.setSize(width,height);
    renderer.render(scene,camera);
    requestAnimationFrame(render);
}

export function seeMeshLabel( name ){
    curObj = css3dLabelXQGroup.getObjectByName(name);
    let position = curObj.position;
    let cameraPosition = new THREE.Vector3(position.x - 630, position.y + 80, position.z - 40);
    let labelPosition = new THREE.Vector3(position.x - 8, position.y - 62, position.z - 56);

    setCamera(cameraPosition, labelPosition);
    curObj.visible = true;
    curObj.userData.visible = true;
}

export function showLwModel(type, showFlag) {
    if (type == 'A') {
        modelAGroup.visible = showFlag;
        css3dLabelGroup.children.map((item,index) => {
            if (item.name.indexOf('A1') != -1 || item.name.indexOf('A2') != -1) {
                item.visible = showFlag;
            }
        })
        modelLcGroup.children.map(item => {
            if (item.name.indexOf('hd-1') != -1 || item.name.indexOf('hd-2') != -1) {
               item.visible = showFlag;
           } 
        })
    } else if (type == 'B') {
        modelBGroup.visible = showFlag;
        css3dLabelGroup.children.map((item,index) => {
            if (item.name.indexOf('A3') != -1 || item.name.indexOf('A4') != -1) {
                item.visible = showFlag;
            }
        })
        modelLcGroup.children.map(item => {
            if (item.name.indexOf('hd-3') != -1 || item.name.indexOf('hd-4') != -1) {
               item.visible = showFlag;
           } 
        })
    }else if (type == 'C') {
        modelCGroup.visible = showFlag;
        css3dLabelGroup.children.map((item,index) => {
            if (item.name.indexOf('B1') != -1 || item.name.indexOf('B2') != -1) {
                item.visible = showFlag;
            }
        })
        modelLcGroup.children.map(item => {
            if (item.name.indexOf('hd-5') != -1 || item.name.indexOf('hd-6') != -1) {
               item.visible = showFlag;
           } 
        })
    }else if (type == 'D') {
        modelDGroup.visible = showFlag;
        css3dLabelGroup.children.map((item,index) => {
            if (item.name.indexOf('B3') != -1 || item.name.indexOf('B4') != -1) {
                item.visible = showFlag;
            }
        })
        modelLcGroup.children.map(item => {
            if (item.name.indexOf('hd-7') != -1 || item.name.indexOf('hd-8') != -1) {
               item.visible = showFlag;
           } 
        })
    }
    
}

export function showAllLabel() {
    modelAGroup.visible = true;
    modelBGroup.visible = true;
    modelCGroup.visible = true;
    modelDGroup.visible = true;
    modelLcGroup.children.map(item => {
        item.visible = true;
    })
    css3dLabelGroup.children.map((item,index) => {
        item.visible = true;
    })
}

// tween
function initControl(){
    if( curObj ){
        curObj.visible = false;
        curObj = undefined;
    }
    setCamera({ 
        x: -1076.6846871989233, y: 408.5020070483296, z: -602.633376408352
    }, {
        x: -60.110525464626186, y: 111.94751770804038, z: 38.011516878125136
    })
}

function moveModel(model) {
    let tween = new TWEEN.Tween(model);
   // tween.to
}

function setCamera(position, target) {
    let tween = new TWEEN.Tween({
      px: controls.object.position.x, // 起始相机位置x
      py: controls.object.position.y, // 起始相机位置y
      pz: controls.object.position.z, // 起始相机位置z
      tx: controls.target.x, // 控制点的中心点x 起始目标位置x
      ty: controls.target.y, // 控制点的中心点y 起始目标位置y
      tz: controls.target.z // 控制点的中心点z 起始目标位置z
    });
    tween.to(
      {
        px: position.x,
        py: position.y,
        pz: position.z,
        tx: target.x,
        ty: target.y,
        tz: target.z
      },
      1000
    );
    tween.onUpdate(function(pos) {
      controls.object.position.x = pos.px;
      controls.object.position.y = pos.py;
      controls.object.position.z = pos.pz;
      controls.target.x = pos.tx;
      controls.target.y = pos.ty;
      controls.target.z = pos.tz;
    });
    tween.easing(TWEEN.Easing.Cubic.InOut);
    tween.start();
  }